/*
 * System.c
 *
 *  Created on: Oct 29, 2018
 *      Author: ax
 */
#define _SOS_VAR_DEFINITION_
//TODO add yours here

#include <Hwi.h>
#include <System.h>
#include <Process.h>
//#include <Semaphore.h>

#include "process.h"
#include "system.h"

#include <Sos.h>



static inline
Process_Handler
__knl(text)
Process_schedual(
    void
){
    if (System_processHaveMark((Process_Status) (Process_DELAY + Process_PEND)))
        Process_timeoutedReschedual();

    Process_Handler cutProcess = Sos.process.merge;
    Process_Handler preSchedual = Sos.process.next;

    if (NULL == cutProcess) {
        if (NULL == preSchedual)
            Sos.process.next = Process_INVALID;
        else {
            #ifdef _DBG
            Sos.process.tick++;
            #endif
            Sos.process.next = preSchedual->next;
        }
        return preSchedual;
    } else {
        System_mark(SOS_PROGRESS_MERGE_SCHEDUAL);

        #ifdef _DBG
        Sos.process.cut++;
        #endif
        Process_remove(cutProcess);
        Process_mark(cutProcess, Process_READY);
        Process_safeInsert(cutProcess, preSchedual);
        return cutProcess;
    }
}


static inline
Process_Status /*__section("text.knl") TODO FIXME*/
Process_run(
    Process_Handler  process,
    Hwi_Key key
){
    int argc =  process->argc;
    void* argv =  process->argv;
    Process prog = (Process) process->entry;

    System_Status status = SOS_PROGRESS_NON_BREAKABLE;
    if (Process_haveMark(process, Process_NON_BREAKABLE)) {
        System_mark(status);
    } else {
        status = SOS_PROGRESS_BREAKABLE;
        System_mark(status);
        Hwi_restore(key);
    }

    Process_Status ps = prog(argc, argv);

    if (SOS_PROGRESS_NON_BREAKABLE == status)
        Hwi_restore(key);

    return ps;
}

static inline void Process_idle(void){
    __asm("\t\t   IDLE");
}

void
System_start(
    void
){
    while (1) {
        Hwi_Key key = Hwi_disable();
        System_mark(SOS_PROGRESS_SCHEDUAL);

        Process_Handler process = Process_schedual();

        if (NULL != process) {
            Process_run(process, key);
        } else {
            System_mark(SOS_IDLE);
            Hwi_restore(key);
            Process_idle();
}   }   }
